package com.excellent.mvvm.base

import android.content.pm.PackageManager
import android.graphics.Rect
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.Window
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.ContextCompat
import androidx.core.view.WindowCompat
import androidx.core.view.isEmpty
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.lifecycle.Lifecycle
import androidx.viewbinding.ViewBinding
import com.excellent.mvvm.R
import com.excellent.mvvm.databinding.BaseViewBinding
import com.excellent.mvvm.event.Message
import com.excellent.mvvm.ext.gone
import com.excellent.mvvm.ext.visible
import com.excellent.mvvm.manager.ActivityManager
import com.excellent.mvvm.widget.loading.LoadingUtils
import java.lang.reflect.ParameterizedType


@Suppress("DEPRECATION")
abstract class BaseActivity<DB : ViewBinding> : AppCompatActivity() {

    protected lateinit var mBinding: DB

    open val layoutId: Int = 0

    lateinit var baseViewBinding: BaseViewBinding

    private val dialogUtils by lazy { LoadingUtils(this) }

    override fun onCreate(savedInstanceState: Bundle?) {
        enableEdgeToEdge()

        super.onCreate(savedInstanceState)
        ActivityManager.push(this)
        initBinding()
        initView()
        initObserve()
        loadData()

        //设置深色模式
        AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
        WindowCompat.getInsetsController(window, window.decorView).isAppearanceLightStatusBars =
            false
    }

    open fun initView() {}
    open fun initObserve() {}
    open fun loadData() {}

    /**
     * 设置状态栏底色颜色
     */
    open fun setStatusBarColor() {
        val window: Window = window
        window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
        window.statusBarColor = resources.getColor(R.color.colorPrimary)

        //设置状态栏字体为白色
        val stateView: View = window.decorView
        var vis = stateView.systemUiVisibility
        vis = vis and View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.inv() //白色
        stateView.systemUiVisibility = vis //设置状态栏字体颜色
    }

    /**
     * DataBinding or ViewBinding
     */
    open fun initBinding() {
        val type = javaClass.genericSuperclass

        val baseViewCls = BaseViewBinding::class.java
        baseViewBinding = baseViewCls.getDeclaredMethod("inflate", LayoutInflater::class.java)
            .invoke(null, layoutInflater) as BaseViewBinding

        if (type is ParameterizedType) {
            val cls = type.actualTypeArguments
                .map { it as Class<*> }
                .first { ViewBinding::class.java.isAssignableFrom(it) }
            when {
                ViewDataBinding::class.java.isAssignableFrom(cls) && cls != ViewDataBinding::class.java -> {
                    if (layoutId == 0) throw IllegalArgumentException("Using DataBinding requires overriding method layoutId")
                    mBinding = DataBindingUtil.setContentView(this, layoutId)
                    (mBinding as ViewDataBinding).lifecycleOwner = this
                    baseViewBinding.flContainer.takeIf { it.isEmpty() }.let {
                        it?.addView(
                            mBinding.root,
                            ViewGroup.LayoutParams.MATCH_PARENT,
                            ViewGroup.LayoutParams.MATCH_PARENT
                        )
                    }
                }

                ViewBinding::class.java.isAssignableFrom(cls) && cls != ViewBinding::class.java -> {
                    cls.getDeclaredMethod("inflate", LayoutInflater::class.java).let {
                        @Suppress("UNCHECKED_CAST")
                        mBinding = it.invoke(null, layoutInflater) as DB
                        if (baseViewBinding.flContainer.isEmpty()) {
                            baseViewBinding.flContainer.addView(
                                mBinding.root,
                                ViewGroup.LayoutParams.MATCH_PARENT,
                                ViewGroup.LayoutParams.MATCH_PARENT
                            )
                        }
                        setContentView(baseViewBinding.root)
                    }
                }

                else -> {
                    if (layoutId == 0) throw IllegalArgumentException("If you don't use ViewBinding, you need to override method layoutId")
                    setContentView(layoutId)
                }
            }
        } else throw IllegalArgumentException("Generic error")
    }


    open fun handleEvent(msg: Message) {}

    /**
     * 打开等待框
     */
    protected fun showLoading(tip: String = "loading...") {
        dialogUtils.showLoading(tip)
    }

    /**
     * 关闭等待框
     */
    protected fun dismissLoading() {
        dialogUtils.dismissLoading()
    }

    open fun showContentView() {
        baseViewBinding.flContainer.visible()
        baseViewBinding.llThrowable.gone()
    }

    open fun showThrowableView() {
        baseViewBinding.flContainer.gone()
        baseViewBinding.llThrowable.visible()
    }

    open fun showEmptyView() {
        showThrowableView()
        baseViewBinding.ivThrowableTip.setImageResource(R.drawable.icon_data_empty)
        baseViewBinding.tvThrowableTip.text = getString(R.string.no_data)
    }

    open fun showNetWorkError() {
        showThrowableView()
        baseViewBinding.ivThrowableTip.setImageResource(R.drawable.icon_net_error)
        baseViewBinding.tvThrowableTip.text = getString(R.string.network_error)
    }

    open fun showSystemError() {
        showThrowableView()
        baseViewBinding.ivThrowableTip.setImageResource(R.drawable.icon_net_error)
        baseViewBinding.tvThrowableTip.text = getString(R.string.system_error)
    }

    override fun dispatchTouchEvent(ev: MotionEvent): Boolean {
        if (ev.action == MotionEvent.ACTION_DOWN) {
            val v = currentFocus
            if (v is EditText) {
                val outRect = Rect()
                v.getGlobalVisibleRect(outRect)
                if (!outRect.contains(ev.rawX.toInt(), ev.rawY.toInt())) {
                    v.clearFocus()
                    val imm = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0)
                }
            }
        }
        return super.dispatchTouchEvent(ev)
    }

    open fun hasPermission(permission: String): Boolean {
        return ContextCompat.checkSelfPermission(
            this,
            permission
        ) == PackageManager.PERMISSION_GRANTED
    }

    open fun requestPermission(permission: String) {
        requestPermissionLauncher.launch(permission)
    }

    protected val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestPermission()
    ) { isGranted: Boolean ->
        onPermissionResult(isGranted)
    }

    open fun onPermissionResult(isGranted: Boolean) {}

    override fun onDestroy() {
        super.onDestroy()
        ActivityManager.pop(this)
    }
}